﻿//-----------------------------------------------------------------------
// <copyright>
//     Copyright (c) Artur Mustafin. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------

#if TRACE
using Parser = Expressions.Compiler.Parser;
#endif


namespace Excel.Application
{
    using System;
    using System.Windows.Forms;
    using Excel.Expressions;
    using Excel.Expressions.Classes;
    using Excel.Expressions.Compiler;

    internal class Core
    {
        private string _fileName;
        private Cell _current;
        private Main _main;

        private TextBox _text;
        private DataGridView _grid;
        private OpenFileDialog _open;
        private SaveFileDialog _save;
        private ErrorProvider _error;

        private Instructions _instructions = new Instructions();

        internal Main Main
        {
            set
            {
                _main = value;
            }
        }

        internal OpenFileDialog OpenDialog
        {
            set
            {
                _open = value;
            }
        }

        internal SaveFileDialog SaveDialog
        {
            set
            {
                _save = value;
            }
        }

        internal DataGridView GridView
        {
            set
            {
                _grid = value;
            }
        }

        internal TextBox TextView
        {
            set
            {
                _text = value;
            }
        }

        internal Cell Current
        {
            get
            {
                return _current;
            }
            set
            {
                _current = value;
            }
        }

        internal void LoadFromFile()
        {
            try
            {
                _open.FileName = _fileName;
                if (_open.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    _fileName = _open.FileName;
                    Clear();
                    Load(_fileName, (cell) =>
                    {
                        _grid.InvalidateCell(_grid.Rows[cell.Row].Cells[cell.Column]);
                    });
                    if (_grid.SelectedCells.Count == 1)
                    {
                        Cell cell = Cell.GetCell(_grid.SelectedCells[0].RowIndex, _grid.SelectedCells[0].ColumnIndex);
                        if (cell != null)
                        {
                            _text.Text = cell.Text;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(_main, ex.Message, string.Format("{0} Exception", _main.Text), MessageBoxButtons.OK);
            }
        }

        internal void Load(string fileName, Action<Cell> action)
        {
            _instructions.Load(fileName, action);
        }

        internal void Save(string fileName)
        {
            _instructions.Save(_save.FileName);
        }

        internal void Clear()
        {
            try
            {
                foreach (Cell cell in _instructions.Cells)
                {
                    DataGridViewCell item = _grid.Rows[cell.Row].Cells[cell.Column];
                    item.Value = null;
                    item.ToolTipText = null;
                }
                _instructions.Clear();
                _text.Text = null;
            }
            catch (Exception ex)
            {
                MessageBox.Show(_main, ex.Message, string.Format("{0} Exception", _main.Text), MessageBoxButtons.OK);
            }
        }

        internal void SaveToFile()
        {
            try
            {
                _save.FileName = _fileName;
                if (_save.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    _fileName = _save.FileName;
                    Save(_fileName);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(_main, ex.Message, string.Format("{0} Exception", _main.Text), MessageBoxButtons.OK);
            }
        }

        internal ErrorProvider ErrorProvider
        {
            set
            {
                _error = value;
            }
        }

        internal void Validate()
        {
            string errorText = null;
            try
            {
                string text = _text.Text;
                if (text == null || string.IsNullOrEmpty(text) || string.IsNullOrWhiteSpace(text))
                {
                    _current.Unsubscribe();
                    _current.Expression = null;
                    _current.Text = null;
                    _current.Visit((cell) =>
                    {
                        _grid.InvalidateCell(_grid.Rows[cell.Row].Cells[cell.Column]);
                    });
                    _instructions.Remove(_current);
                    _error.SetError(_text, null);
                    return;
                }
                if (_current.Text != text)
                {
                    _current.BeginUpdate();
#if TRACE
                    Parser.ClearTraceLog();
#endif
                    CellExpression expression = Text.Parse(text);
                    if (expression == null)
                    {
                        throw new NotSupportedException("Input string was not in correct format");
                    }
                    if (!_current.Validate(expression))
                    {
                        throw new NotSupportedException("Initialization of the circle referenced instruction is not supported");
                    }
#if TRACE
                    Parser.WriteTraceLog();
#endif
                    _instructions.Update(_current, text, expression, (cell) =>
                    {
                        _grid.InvalidateCell(_grid.Rows[cell.Row].Cells[cell.Column]);
                    });
                }
                _current.EndUpdate();
            }
            catch (Exception ex)
            {
                _current.CancelUpdate();
                errorText = ex.Message;
            }
            _error.SetError(_text, errorText);
        }
    }
}
